# 自 动 挂 DOOM，可 以 自 动 喂 宠 物、自 动 更 换 无 耐 久 的 武 器、自 动 保 险 获 取 的 doom 神 器、自 动 更 换 法 师 的 屠 杀 书
# 1.在 boss 房 间 区 域 外 运 行 脚 本
# 2.包 中 放 一 把 剑 类 武 器 用 于 剔 骨
# by Blood Lover 2022.01.20
# version 22.02.05.1
#--------------下 面 设 置 相 关 参 数---------------------#
#职 业 1战 士 2弓 手 3巫 法 
profession = 3
#是 否 使 用 宠 物 攻 击 0不 使 用  1使 用 不 可 乘 骑 的 宠 物  2使 用 可 乘 骑 的 宠 物
usePet = 2

#用 于 更 换 的 备 用 武 器 图 片 id，可 以 是 多 种 类 型，如 果 为 空，自 动 使 用 手 中 的 同 类 型 武 器
weaponList = [
    # 0x908098,
    # 0x908098,
]

#给 谁 使 用 绷 带  0-不 使 用  1-自 己 和 自 己 的 宠 物(自 动 检 测 治 疗 和 兽 医 技 能，低 于 25 不 使 用 ) 2-RAE 设 置 的 朋 友、自 己  3-所 有 蓝 名 
useBandage = 1
# 给 谁 使 用 魔 法 或 者 骑 士 加 血 0-不 使 用  1-自 己 和 自 己 的 宠 物  2-RAE设 置 的 朋 友、自 己  3-所 有 蓝 名
useMagicHeal = 1
#使 用 魔 法 还 是 骑 士 精 神 加 血 0-根 据 省 药 数 值 判 断 1-骑 士 精 神 2-魔 法
useSkill = 2 
selflow = 0.80      # 绷 带 加 血 自 己 血 量 少 于 百 分 之 多 少 开 始 加 血 
otherlow = 0.80     # 绷 带 加 血 其 他 血 量 少 于 百 分 之 多 少 开 始 加 血
selflowMig = 0.60   # 魔 法 加 血 自 己 血 量 少 于 百 分 之 多 少 开 始 加 血 
otherlowMig = 0.60  # 魔 法 加 血 其 他 血 量 少 于 百 分 之 多 少 开 始 加 血
# 血 量 低 于 设 定 值 后 是 否 加 满
isRecoverMaxHP = True

# 血 量 低 于 多 少 百 分 比 远 离 敌 人
keepAwayFlow = 0.6
# 需 要 保 持 的 buff 需 要 保 持 的 就 去 掉 前 面 的 #, 不 需 要 前 面 就 加 #
# 骑 士 精 神 的 buff
chivalryBuffs = [
    # 法 术 名 字，消 耗 的 mana
    ('Enemy Of One', 20),#最终对手 死敌
    # ('Divine Fury', 15),#神圣愤怒 增加体力恢复速度
    # ('Consecrate Weapon', 10),#神圣武器
]
#武 士 道 的 buff
bushidoBuffs = [
    # ('Lightning Strike', 10),#闪电击
    ('Counter Attack', 5),#反击
]
#魔 法 buff
mageryBuffs = [
    ('Protection', 10),#盾防
]
#专 精 buff
masteryBuffs = [
    ('Shield Bash', 40),#盾击
]
# 是 否 使 用 主 特 攻 战 士、弓 手 职 业 有 效 
isUesPrimarySA = True
#喂 食 间 隔 
feedTime = 20 * 60 * 1000  #多 少 分 钟 喂 一 次 第 一 个 数 字 代 表 分 钟 数
# 如 果 包 里 没 食 物，是 否 使 用 魔 法 造 食 物 
isCreateFood = True

# 需 要 自 动 保 险 的 doom 神 器  不 需 要 保 险 的 物 品 前 面 加 #
insuranceDoomArtifacts = [
    'Aegis',#宙斯盾 埃吉斯
    'Arcane Shield',#奥术护盾
    'Armor of Fortune',#命运之盔甲
    'Axe of the Heavens',#天堂斧
    'The Berserker\'s Maul',#狂战士之槌
    'Blade of Insanity',#疯狂之刃
    'Bone Crusher',#碎骨机
    'Bracelet of Health',#生命手镯
    'Breath of the Dead',#死者之息
    'The Deceiver',#欺骗者
    'Divine Countenance',#神圣的面容
    'The Dragon Slayer',#屠龙者
    'The Dryad Bow',#树妖弓
    'Frostbringer',#冰霜使者
    'Gauntlets of Nobility',#贵族护手
    'Glenda',#格伦达
    'Hat of the Magi',#魔法师的帽子
    'Helm of Insight',#洞察头盔
    'Holy Knight\'s Breastplate',#圣骑士的胸甲
    'Hunter\'s Headdress',#猎人的头饰
    'bow of the infinite swarm',#无限虫群之弓
    'Jackal\'s Collar',#豺狼的项圈 剑脖
    'Legacy of the Dread Lord',#恐惧领主的遗产
    'Leggings of Bane',#厄运护腿 绿腿
    'Midnight Bracers',#午夜护腕 巫臂
    'Ornament of the Magician',#魔法师的饰品 蓝手镯
    'Ornate Crown of the Harrower',#耙者的华丽王冠
    'Ring of the Elements',#元素戒指
    'Ring of the Vile',#邪恶之戒
    'the scholar\'s halo',#学者的光环
    'Serpent\'s Fang',#蛇牙
    'Shadow Dancer Leggings',#影舞者护腿
    'Spirit of the Totem',#图腾之魂
    'Staff of the Magi',#法师之杖
    'The Taskmaster',#工头
    'Tunic of Fire',#火焰外套
    'Voice of the Fallen King',#堕落之王的声音
]
# 消 除 地 上 骨 头 用 的 到 的 武 器 对 象 id serial，不 设 置 的 话 会 自 动 使 用 包 中 的 剑 类 武 器
BladesId = 0
# 法 师 用 的 屠 杀 书 如 果 设 置 为 0 则 自 动 检 测 包 中 的 屠 杀 书
undeadBook = 0 #不 死
demonBook = 0  #恶 魔
SCBook = 0     #拳 击 手 册 
# 脚 本 名 称，如 果 改 名 了 这 里 也 要 做 修 改
scriptName = '自动巫训打DOOM.py'
# 是 否 是 Demise 站 D 站 打 黑 爹 用 卡 位 的 方 式
isDemise = True
#---------------------设 置 参 数 完 毕-----------------------------#
# import threading
from System.Collections.Generic import List
from System import Byte
import sys
if(sys.version[:1] == "3"):import _thread as thread
# 如 果 版 本 号 是 3
else:import thread
# 任 务 状 态 0 未 知 状 态 1 去 往 boss 区 2 boss 区 域 boss 未 死 3 boss 区 域 boss 已 死 
# 4 去 往 第 一 房 间 门 口 5 第 一 房 间 内 boss 未 死 6 第 一 房 间 boss 已 死 
# 7 去 往 第 二 房 间 门 口 8 第 二 房 间 内 boss 未 死 9 第 二 房 间 boss 已 死 
# 10 去 往 第 三 房 间 门 口 11 第 三 房 间 内 boss 未 死 12 第 三 房 间 boss 已 死 
# 13 去 往 第 四 房 间 门 口 14 第 四 房 间 内 boss 未 死 15 第 四 房 间 boss 已 死 
# 16 去 往 第 五 房 间 门 口 17 第 五 房 间 内 boss 未 死 18 第 五 房 间 boss 已 死 
taskState = 0
isRecoverHP = False

chivalrySkill = Player.GetSkillValue('Chivalry')
magerySkill = Player.GetSkillValue('Magery')
healingSkill = Player.GetSkillValue('Healing')
veterinarySkill = Player.GetSkillValue('Veterinary')
bushidoSkill = Player.GetSkillValue('Bushido')
necromancySkill = Player.GetSkillValue('Necromancy')
if useSkill == 0:
    if Player.LowerReagentCost == 100:
        useSkill = 2# 使 用 魔 法
    else:
        useSkill = 1# 使 用 骑 士 精 神


# boss 区 域 坐 标 黑 爹 图 片 id 0x013E
BossAreaPoint = [
    (433, 429),
    (446, 429),
    
]
attackBossPoint = [
    (453, 419),
]
# 去 往 1 号 房
toRoom1Point = [ 
    (459, 430),
    # (470, 429),# 传 送 踏 板 前
    (472, 428),# 传 送 踏 板 
]
#1号 房 
room1Point = [ 
    (488, 450),
]
#离 开 1号 房
room1OutPoint = [ 
    (474, 433),
]
#去 往 2号 房
toRoom2Point = [ 
    (465, 483),
    # (463, 493),
    (462, 494),
]
#2号 房 
room2Point = [ 
    (476, 509),
]
#离 开 2号 房
room2OutPoint = [ 
    (468, 497),
]
#去 往 3号 房
toRoom3Point = [ 
    (410, 490),
    # (404, 501),
    (403, 502),
]
#3号 房
room3Point = [ 
    (407, 530),
]
#离 开 3号 房
room3OutPoint = [ 
    (408, 506),
]
#去 往 4号 房
toRoom4Point = [ 
    (409, 456),
    (374, 465),
    # (358, 475),
    (357, 476),
]
#4号 房
room4Point = [ 
    (340, 504),
]
#离 开 4号 房 
room4OutPoint = [ 
    (361, 480),
]
#4号 房 找 boss放 群 攻 的 点
room4FindBossPoint = [
    (345, 498),
    (328, 498),
    (328, 515),
    (345, 515),
    (345, 498),

    (341, 502),
    (332, 502),
    (332, 511),
    (341, 511),
    (341, 502),

    (338, 505),
    (335, 508),
    (338, 505),

    (348, 495),
    (337, 491),
    (325, 495),
    (322, 506),
    (324, 518),
    (336, 522),
    (348, 518),
    (352, 507),
    (348, 495),
]
#去 往 5号 房
toRoom5Point = [ 
    (375, 431),
    # (362, 432),
    (361, 433),
]
#5号 房
room5Point = [ 
    (337, 429),
]
#离 开 5号 房
room5OutPoint = [ 
    (359, 429),
]
#检 测 当 前 开 启 的 是 哪 个 门 的 坐 标 点
# checkRoomStatePoints = [
#     (433, 429),
#     (459, 430),
#     (465, 483),
#     (410, 490),
#     (374, 465),
#     (375, 431),
# ]
#test
roomTestPoint = [ 
    (404, 501),
    (403, 502),
]

pathStep = 0
tarCheckSer = 0
gotoCount = 0

#刻用于剔骨的武器类型
# bladeTypes = [
#     'Swordsmanship',#剑类
# ]

#吃肉宠物的图形id mobileId
eatMeatPet = [
    0x00C6,#超龙
    0x00C5,#小龙
    0x04E6,#老虎
    0x05A1,#骷髅老虎
]
#吃水果宠物的图形id mobileId
eatFruitPet = [
    0x0115,#精灵狼
    0x011C,#战马
    0x00E4,#马
]


#肉食的图形id mobileId
meatID = [
    0x09B7,#煮熟的鸟
    0x09F2,#肋肉片
    0x1608,#鸡腿
    0x160A,#羊腿
    0x09C0,#香肠
    0x09C9,#火腿
]
#水果的图形id mobileId
fruitID = [
    0x09D0,#苹果
    0x09D1,#葡萄
    0x09D2,#桃子
    0x171F,#香蕉
    0x0994,#梨子
]

#玩家的坐骑
playerMount = None

#4号 boss状 态 0-未 开 始 打 1-已 开 始 打 2-准 备 隐 身 阶 段 3-已 隐 身 4-反 隐 后
boss4State = 0

layerName = 'RightHand'
#设 置 武 器
def setWeapons():
    if profession > 2:
        return
    global layerName
    if weaponList is not None and len(weaponList) == 0:
        # weaponID = Target.PromptTarget("选择备用武器，全部选择完毕后按ESC键", 33)
        # while weaponID > 0:
        #     weaponList.append(weaponID)
        #     weaponID = Target.PromptTarget("选择备用武器，全部选择完毕后按ESC键", 33)
        handWeapon = Player.GetItemOnLayer('RightHand')
        if handWeapon is None:
            handWeapon = Player.GetItemOnLayer('LeftHand')
            if handWeapon is not None:
                layerName = 'LeftHand'
                weaponList.append(handWeapon.ItemID)
                Misc.SendMessage('weaponList.append ' + str(handWeapon.ItemID), 255)
        else:
            weaponList.append(handWeapon.ItemID)
            Misc.SendMessage('weaponList.append ' + str(handWeapon.ItemID), 255)
#检 测 武 器 耐 久
def checkWeaponsDurability():
    if profession > 2:
        return
    global layerName
    handWeapon = Player.GetItemOnLayer(layerName)
    if handWeapon is None or handWeapon.Durability == 0:
        if weaponList is not None and len(weaponList) > 0:
            handWeapon = Player.GetItemOnLayer(layerName)
            if handWeapon:
                Player.UnEquipItemByLayer(layerName, 1000)
            Misc.Pause(700)
            for weaponID in weaponList:
                for item in Player.Backpack.Contains:
                    if item.ItemID == weaponID and item.Durability > 0:
                        Player.EquipItem(item)
                        Misc.SendMessage('change weapon ' + Items.GetPropStringByIndex(item,0), 255)
                        Misc.Pause(600)
                        return

#设置消除地上骨头的刀
def setBlades():
    global BladesId
    if BladesId == 0:
        # BladesId = Target.PromptTarget("选择用于剔除地上骨头的刀", 33)
        for item in Player.Backpack.Contains:
            # Misc.SendMessage('setBlades ' + item.Name)
            if Items.GetPropValue(item,'Swordsmanship'):
                BladesId = item.Serial
                Misc.SendMessage('setBlades ' + item.Name)
                break

#设置法师的屠杀书
def setMagicSlayerBook():
    if profession != 3:
        return
    global undeadBook
    global demonBook
    global SCBook
    handWeapon = Player.GetItemOnLayer('RightHand')
    if handWeapon:
        if handWeapon.ItemID == 0x0EFA:
            if Items.GetPropValue(handWeapon,'Undead Slayer') and undeadBook == 0:
                undeadBook = handWeapon.Serial
                Misc.SendMessage('find Undead Slayer boos' + handWeapon.Name)
            elif Items.GetPropValue(handWeapon,'Demon Slayer') and demonBook == 0:
                demonBook = handWeapon.Serial
                Misc.SendMessage('find Demon Slayer boos' + handWeapon.Name)
            elif Items.GetPropStringByIndex(handWeapon,0) == 'Scrapper\'s Compendium' and SCBook == 0:
                SCBook = handWeapon.Serial
                Misc.SendMessage('find Scrapper\'s Compendium boos' + handWeapon.Name)
    for item in Player.Backpack.Contains:
        # Misc.SendMessage('setBlades ' + item.Name)
        if item.ItemID == 0x0EFA:
            if Items.GetPropValue(item,'Undead Slayer') and undeadBook == 0:
                undeadBook = item.Serial
                Misc.SendMessage('find Undead Slayer boos' + item.Name)
            elif Items.GetPropValue(item,'Demon Slayer') and demonBook == 0:
                demonBook = item.Serial
                Misc.SendMessage('find Demon Slayer boos' + item.Name)
            elif Items.GetPropStringByIndex(item,0) == 'Scrapper\'s Compendium' and SCBook == 0:
                SCBook = item.Serial
                Misc.SendMessage('find Scrapper\'s Compendium boos' + item.Name)
                
#检测更换屠杀书
def checkMagicSlayerBook():
    if profession != 3:
        return
    handWeapon = Player.GetItemOnLayer('RightHand')
    changeWeapnID = 0
    if taskState == 5 or taskState == 14: # 1、4房间不死
        if undeadBook > 0:
            if handWeapon:
                if not Items.GetPropValue(handWeapon,'Undead Slayer'):
                    changeWeapnID = undeadBook
            else:
                changeWeapnID = undeadBook
    elif taskState == 2 or taskState == 11: # 3、DF房间恶魔
        if demonBook > 0:
            if handWeapon:
                if not Items.GetPropValue(handWeapon,'Demon Slayer'):
                    changeWeapnID = demonBook
            else:
                changeWeapnID = demonBook
    elif taskState == 8 or taskState == 17: # 2、5房间拳击书
        if SCBook > 0:
            if handWeapon:
                if not Items.GetPropStringByIndex(handWeapon,0) == 'Scrapper\'s Compendium':
                    changeWeapnID = SCBook
            else:
                changeWeapnID = SCBook
    if changeWeapnID > 0:
        weapon = Items.FindBySerial(changeWeapnID)
        if weapon:
            if handWeapon:
                Player.UnEquipItemByLayer('RightHand', 1000)
                Misc.Pause(600)
            Player.EquipItem(weapon)
            Misc.SendMessage('change weapon ', 255)
            # Misc.Pause(600)




#宠 物 列 表
petList = []
petid = 0#Player.StaticMount
#检 测 自 己 有 哪 些 宠 物
def checkSelfPets():
    if usePet == 0:
        return
    i = 0
    while i < 1:
        Player.ChatSay(0,"all come")
        i += 1
        Misc.Pause(1000)
    fil = Mobiles.Filter()
    fil.Enabled = True
    fil.IsHuman = False
    # fil.RangeMin = -1
    # fil.RangeMax = 16
    fil.Notorieties = List[Byte](bytes([1,2]))
    mobs = Mobiles.ApplyFilter(fil)
    # lastMob = None
    if mobs is not None and len(mobs) > 0:
        for mob in mobs:
            isOK = -1
            if not isHuman(mob):
                for i in range(8):
                    isOK = Mobiles.ContextExist(mob, 'Command: Guard')
                    Misc.Pause(100)
                    if isOK > -1:
                        break
                if isOK > -1:
                    Misc.SendMessage('mob append' + mob.Name, 33)
                    petList.append(mob.Serial)
            Misc.Pause(100)
    oldLen = len(petList)
    if usePet == 2 and Player.Mount is not None:
        global playerMount
        global petid
        # if Player.Mount.Serial:
        #     petList.append(Player.Mount.Serial)
        #     Misc.SendMessage('mob append Player.Mount.Serial ' + str(Player.Mount.Serial), 33)
            
        #     petid = Player.Mount.Serial
        #     playerMount = Player.Mount
        #     return
         #下马
        Mobiles.UseMobile(Player.Serial)
        Misc.Pause(600)
        Player.ChatSay(0,"all come")
        fil = Mobiles.Filter()
        fil.Enabled = True
        fil.IsHuman = False
        # fil.RangeMin = -1
        # fil.RangeMax = 16
        fil.Notorieties = List[Byte](bytes([1,2]))
        mobs = []
        mobs = Mobiles.ApplyFilter(fil)
        Misc.SendMessage('mobs ' + str(len(mobs)), 33)
        if mobs is not None and len(mobs) > 0:
            for mob2 in mobs:
                isOK = -1
                if not isHuman(mob2):
                    for i in range(8):
                        isOK =  Mobiles.ContextExist(mob2, 'Command: Guard')
                        Misc.Pause(100)
                        if isOK > -1:
                            break
                    if isOK > -1:
                        if petList.count(mob2.Serial) == 0:
                            Misc.SendMessage('mob2 append ' + mob2.Name, 33)
                            petList.append(mob2.Serial)
                Misc.Pause(100)
        curLen = len(petList)
        if curLen > oldLen:
            playerMount = Mobiles.FindBySerial(petList[curLen - 1])
            if playerMount is not None:
                petid = playerMount.Serial
                Mobiles.UseMobile(playerMount)
        Misc.Pause(500)
        Misc.LeftMouseClick(200, 200)
#返 回 狗 朝 向
def ZouWei():
    PetMobil = Mobiles.FindBySerial(petid)
    fangx = PetMobil.Direction
    LHXL = PathFinding.Route()
    if fangx == 'Down':
        LHXL.X = PetMobil.Position.X - 1
        LHXL.Y = PetMobil.Position.Y - 1
        fx = 1
    elif fangx == 'up':
        LHXL.X = PetMobil.Position.X + 1
        LHXL.Y = PetMobil.Position.Y + 1
        fx = 2
    elif fangx == 'Right':
        LHXL.X = PetMobil.Position.X - 1
        LHXL.Y = PetMobil.Position.Y + 1
        fx = 3
    elif fangx == 'Left':
        LHXL.X = PetMobil.Position.X + 1
        LHXL.Y = PetMobil.Position.Y - 1
        fx = 4
    elif fangx == 'North':
        LHXL.X = PetMobil.Position.X
        LHXL.Y = PetMobil.Position.Y + 1
        fx = 5
    elif fangx == 'South':
        LHXL.X = PetMobil.Position.X
        LHXL.Y = PetMobil.Position.Y - 1
        fx = 6
    elif fangx == 'East':
        LHXL.X = PetMobil.Position.X - 1
        LHXL.Y = PetMobil.Position.Y
        fx = 7
    elif fangx == 'West':
        LHXL.X = PetMobil.Position.X + 1
        LHXL.Y = PetMobil.Position.Y
        fx = 8
    else:
        LHXL.X = PetMobil.Position.X
        LHXL.Y = PetMobil.Position.Y    
        fx = 0

    autorun([LHXL.X,LHXL.Y])
            
    BossWZ = [fx,PetMobil.Position.X,PetMobil.Position.Y]        
    return BossWZ        
#烧 4 号 Boss
def DetectFourBoss(BWZ):
    if BWZ[0] == 1:
        BX = BWZ[1] + 1
        BY = BWZ[2] + 1
    elif BWZ[0] == 2: 
        BX = BWZ[1] - 1
        BY = BWZ[2] - 1
    elif BWZ[0] == 3: 
        BX = BWZ[1] + 1
        BY = BWZ[2] - 1   
    elif BWZ[0] == 4: 
        BX = BWZ[1] - 1
        BY = BWZ[2] + 1
    elif BWZ[0] == 5: 
        BX = BWZ[1]
        BY = BWZ[2] - 1
    elif BWZ[0] == 6: 
        BX = BWZ[1]
        BY = BWZ[2] + 1   
    elif BWZ[0] == 7: 
        BX = BWZ[1] + 1
        BY = BWZ[2]
    elif BWZ[0] == 8: 
        BX = BWZ[1] - 1
        BY = BWZ[2]
    else:
        BX = BWZ[1]
        BY = BWZ[2]
        
    if Player.Mana >= 10:
        Spells.CastMagery("Fire Field")
        Target.WaitForTarget(10000, False)
        Target.TargetExecute(BX,BY,-1) 
        Misc.Pause(600)
    else:
        Player.HeadMessage(53,"等 待 法 力 恢 复")  
        Misc.Pause(1000)
        
    #if Player.Mana >= 16:    
        #Spells.CastMagery("Reveal")
        #Target.WaitForTarget(10000, False)
        #Target.TargetExecute(BX,BY,-1)
        #Misc.Pause(4000)        
    #else:
        #Player.HeadMessage(53,"等 待 法 力 恢 复")
        #Misc.Pause(1000)
    
#pet come back
def petcome():
    p = Mobiles.FindBySerial(petid)
    i = 0
    while p is not None and i < 5:
        i += 1
        Player.ChatSay(33,"all come")
        if Player.DistanceTo(p) > 1:
            Misc.Pause(500)
            Player.ChatSay(33,"all come")
        elif usePet == 2 and not Player.Mount:
            if isHuman():
                Mobiles.UseMobile(p)
                Misc.Pause(200)
                if Player.Mount:
                    break
            p = Mobiles.FindBySerial(petid)
            Misc.Pause(100)

#喂 宠 物
def feedPet():
    petcome()
    isRided = False
    if usePet == 2 and Player.Mount is not None:
        #下马
        Mobiles.UseMobile(Player.Serial)
        Misc.Pause(200)
        Player.ChatSay(0,"all come")
        isRided = True
    for pid in petList:
        p = Mobiles.FindBySerial(pid)
        if p is not None:
            eatType = getPetEatType(p.MobileID)
            if eatType == 1:
                food = getMeat()
                if food is not None:
                    Items.Move(food, p, 1)
                    Misc.Pause(600)
            elif eatType == 2:
                food = getFruit()
                if food is not None:
                    Items.Move(food, p, 1)
                    Misc.Pause(600)
            else:
                food = getMeat()
                if food is not None:
                    Items.Move(food, p, 1)
                    Misc.Pause(600)
                food = getFruit()
                if food is not None:
                    Items.Move(food, p, 1)
                    Misc.Pause(600)
    p = Mobiles.FindBySerial(petid)
    if isRided and usePet == 2 and p:
        #上马
        Player.ChatSay(0,"all come")
        Misc.Pause(600)
        Mobiles.UseMobile(p)
        Player.ChatSay(0,"all guard me")
#获取包中肉食
def getMeatFromBag():
    for mId in meatID:
        meat = Items.FindByID(mId,-1,Player.Backpack.Serial)
        if meat is not None:
            return meat
    return None

#获取包中水果
def getFruitFromBag():
    for fId in fruitID:
        fruit = Items.FindByID(fId,-1,Player.Backpack.Serial)
        if fruit is not None:
            return fruit
    return None

#获取肉食
def getMeat():
    meat = getMeatFromBag()
    if meat is None and isCreateFood:
        for idx in range(30):
            Spells.CastMagery('Create Food')
            Misc.Pause(800)
            meat = getMeatFromBag()
            if meat is not None:
                return meat
    return meat
#获取水果
def getFruit():
    fruit = getFruitFromBag()
    if fruit is None and isCreateFood:
        for idx in range(30):
            Spells.CastMagery('Create Food')
            Misc.Pause(600)
            fruit = getFruitFromBag()
            if fruit is not None:
                return fruit
    return fruit

#根据宠物的图片ID判断宠物吃肉还是吃素 0未知 1吃肉 2吃素
def getPetEatType(petMobileId):
    if eatMeatPet.count(petMobileId) > 0:
        return 1
    elif eatFruitPet.count(petMobileId) > 0:
        return 2
    return 0
            
def petkill(t):
    # Misc.SendMessage('petkill enemy ', 25) 
    global tarCheckSer
    if usePet == 2 and Player.Mount is not None:
        Mobiles.UseMobile(Player.Serial)
        # Mobiles.ContextExist(p, 'Command: Follow')
        Misc.Pause(600)
    # Misc.SendMessage('petkill 1 ', 25) 
    if t and petList is not None:
        # Misc.SendMessage('petkill 2 ' , 25)
        try:
            isComp = True
            for petid in petList:
                p = Mobiles.FindBySerial(petid)
                if not p:
                    # Misc.SendMessage('petkill 3 p is None ', 25) 
                    continue
                if not isDemise:
                    if Mobiles.GetPropValue(petid,'guard') == False:
                        Player.ChatSay(23, "all guard me")
                else:
                    # isOK = -1
                    # if p:
                    #     isOK = Mobiles.ContextExist(p, 'Command: Kill')
                    # Misc.SendMessage('petkill 4 ', 25) 
                    Mobiles.WaitForProps(p, 1000)
                    if (tarCheckSer != t.Serial or (not p.WarMode)):
                        # commandIdx = Mobiles.ContextExist(p, 'Command: Kill')
                        # if commandIdx > -1:
                            # Player.ChatSay(23, "all guard me")
                            # for i in range(2):
                            Player.ChatSay(53,"all kill")
                            Target.WaitForTarget(10000, False)
                            Target.TargetExecute(t)
                            Misc.SendMessage('petkill enemy ' + '  ' + t.Name, 25) 
                            Misc.Pause(200)
                            # Misc.WaitForContext(p, 5000)
                            # Misc.ContextReply(p, 'Command: Kill')
                            # Target.WaitForTarget(5000, True)
                            # Target.TargetExecute(t)
                        # else:
                        #     Misc.Pause(400)
                        #     isComp = False
                    else:
                        isComp = False
            if isComp:
                tarCheckSer = t.Serial
        except Exception as e:
            Misc.SendMessage('异 常: ' + str(e),88)

#荣 誉 目 标
def honorTarget(t):
    if t and t.Hits == t.HitsMax:
        Player.InvokeVirtue('Honor')
        Target.WaitForTarget(3000, True)
        Target.TargetExecute(t)

#攻 击 附 近 敌 人        
def attackEnemy():
    t = findboss()
    if not t is None:
        #满 血 就 先 荣 誉 一 下
        if t.Hits == t.HitsMax:
            Player.InvokeVirtue('Honor')
            Target.WaitForTarget(3000, True)
            Target.TargetExecute(t)
        if usePet > 0:
            petkill(t)
        playerkill(t)
        Misc.Pause(300)

def doAttackTar(param):
    while Misc.ScriptStatus(scriptName):
        # Misc.SendMessage('attacktar ', 25)
        t = findboss()
        if not t is None:
            playerkill(t)
            if usePet > 0:
                petkill(t)
            # t = Target.GetTargetFromList(tlist)
            # t = getNearestEnemy()
            Misc.Pause(300)
        Misc.Pause(100)
        
#保 持 buff与 特 攻
def checkAttackBuff():
    if not Player.IsGhost:
        if profession < 3: #战士弓手buff
            for cBuff in chivalryBuffs:
                if not Player.BuffsExist(cBuff[0]) and Player.Mana >= cBuff[1]:
                    Spells.CastChivalry(cBuff[0])
                    if cBuff[0] == 'Enemy Of One':
                        Misc.SendMessage('checkAttackBuff 1 ' , 25)
                        Misc.Pause(2000)
                    else:
                        Misc.Pause(800)
            for bBuff in bushidoBuffs:
                if not Player.BuffsExist(bBuff[0]) and Player.Mana >= bBuff[1]:
                    Spells.CastBushido(bBuff[0])
                    if bBuff[0] == 'Counter Attack':
                        Misc.Pause(2000)
                    else:
                        Misc.Pause(1600)
            isHaveMasteryBuffs = True
            if profession == 1: #战士buff
                for mBuff in masteryBuffs:
                    if not Player.BuffsExist(mBuff[0]) and Player.Mana >= mBuff[1]:
                        Spells.CastMastery(mBuff[0])
                        Misc.Pause(600)
            if len(masteryBuffs) > 0:
                for mBuff in masteryBuffs:
                    if not Player.BuffsExist(mBuff[0]):
                        isHaveMasteryBuffs = False
            # Misc.SendMessage('Player.HasSpecial '+ str(Player.HasSpecial), 25)
            if isHaveMasteryBuffs and isUesPrimarySA and not Player.HasSpecial and Player.Mana >= 17: 
                Player.WeaponPrimarySA()
                Misc.Pause(1200)
        else: #法师buff
            for mBuff in mageryBuffs:
                if not Player.BuffsExist(mBuff[0]) and Player.Mana >= mBuff[1]:
                    Spells.CastMagery(mBuff[0])
                    Misc.Pause(600)

#靠 近 目 标
def closeToTarget(t):
    if t:
        Tx = t.Position.X
        Ty = t.Position.Y
        distance = Player.DistanceTo(t)
        petDis = 0
        p = None
        if usePet > 0:
            p = Mobiles.FindBySerial(petid)
            if p:
                petDis = Player.DistanceTo(p)
        if profession == 1 and distance >= 2:
            Misc.SendMessage('playerkill 2 ' , 25)
            tileList = PathFinding.GetPath(Tx,Ty, True)
            # Misc.SendMessage('playerkill need findPath ' + str(len(tileList)), 25)
            if tileList is not None and len(tileList) > 0:
                length = len(tileList)
                # gotoByFindPath([tileList[length - 1].X,tileList[length - 1].Y], False)
                # Misc.SendMessage('playerkill findPath start ', 25)
                autorun([tileList[length - 1].X,tileList[length - 1].Y])
                # Misc.SendMessage('playerkill findPath end ', 25)
                Misc.Pause(50)
        elif profession > 1 and usePet == 0 and (taskState != 2 or not isDemise) and distance < 2 :
            Misc.SendMessage('playerkill 3 ' , 25)
            keepAwayFromTarget(t, 3) 
            # Misc.SendMessage('playerkill 3 ' , 25)
        elif distance > 7:
            Misc.SendMessage('playerkill 4 ' , 25)
            tileList = PathFinding.GetPath(Tx,Ty, False)
            if tileList is not None and len(tileList) > 6:
                autorun([tileList[5].X,tileList[5].Y])
                Misc.Pause(50)
        elif profession > 1 and p and p.WarMode and usePet > 0 and (petDis > 2 or distance < 2 or distance > 3):
            Misc.SendMessage('playerkill 5 ' , 25)
            gotoBehindPetPosition()

#玩 家 攻 击
def playerkill(t):
    # magicHealing()
    if t and Player.Hits > Player.HitsMax * keepAwayFlow and not isRecoverHP:
        # Misc.SendMessage('playerkill 1 ' , 25)
        Target.SetLast(t)
        Player.Attack(t)    
        closeToTarget(t)
        checkAttackBuff()
        if profession > 2:#法师
            # Misc.SendMessage('playerkill 4 ' , 25)
            magicAttack(t)
            # Misc.SendMessage('playerkill 5 ' , 25)

#魔 法 攻 击
def magicAttack(target):
    #变 鬼
    if isHuman():
        changeWraithForm()
        # Misc.SendMessage('playerkill 6 ' , 25)
        return
    #定 时 腐 皮
    if taskState != 14 and taskState != 17 and Timer.Check('CorpseSkinTime') is False:
        Spells.CastNecro("Corpse Skin")
        Target.WaitForTarget(5000, True)
        Target.TargetExecute(target)
        Misc.Pause(100)
        if Player.BuffsExist("Protection"):
            Misc.Pause(200)
        Timer.Create('CorpseSkinTime', 40 * 1000)
    # Misc.SendMessage('playerkill 7 ' , 25)
    if target.Hits <= 0:
        return

    if taskState == 14:#4号房
        if target.Hits <= 0:
            return
        if Player.Mana >= 7:
            Spells.CastMagery("Lightning")
            Target.WaitForTarget(5000, True)
            Target.TargetExecute(target)
            # Misc.Pause(100)
            if Player.BuffsExist("Protection"):
                Misc.Pause(200)
    elif taskState == 17:#5号房
        # if Player.Mana >= 15:
        #     Spells.CastNecro("Poison Strike")
        #     Target.WaitForTarget(5000, True)
        #     Target.TargetExecute(target)
        #     # Misc.Pause(200)
        #     if Player.BuffsExist("Protection"):
        #         Misc.Pause(100)
        # else:
        #     Misc.Pause(1000)
        # Misc.Pause(500)        
        if target.Hits <= 0:
            return
        if Player.Mana >= 5:        
            Spells.CastMagery("Harm")
            Target.WaitForTarget(2000, True)
            Target.TargetExecute(target)
            # Misc.Pause(100)
            if Player.BuffsExist("Protection"):
                Misc.Pause(100)
        # else:
            # Misc.Pause(1000)
        # Misc.Pause(100)
    else:
        if target.Hits <= 0:
            return
        if Player.Mana >= 7:
            Spells.CastMagery("Fireball")
            Target.WaitForTarget(2000, True)
            Target.TargetExecute(target)
            # Misc.Pause(100)
            if Player.BuffsExist("Protection"):
                Misc.Pause(200)
        # else:
        #     Misc.Pause(1000)  
        # Misc.SendMessage('playerkill 8 ' , 25)
        if target.Hits <= 0:
            return
        if Player.Mana >= 3:        
            Spells.CastMagery("Magic Arrow")
            Target.WaitForTarget(2000, True)
            Target.TargetExecute(target) 
            # Misc.Pause(100)
            if Player.BuffsExist("Protection"):
                Misc.Pause(100)
        # else:
        #     Misc.Pause(1000)
        # Misc.SendMessage('playerkill 9 ' , 25)

pathBuffer = {}
#获取服务器寻路路径，优先从缓冲中取，如果没有从服务器获取，获取后放入缓存
def getPath(x, y):
    key = str(Player.Position.X) + ',' + str(Player.Position.Y) + ',' + str(x) + ',' + str(y)
    if key in pathBuffer:
        Misc.SendMessage('get path from buffer', 255)
        return pathBuffer[key]
    else:
        path = PathFinding.GetPath(x, y,True)
        pathBuffer[key] = path
        return path

def onestep(x1,y1):  
    x = Player.Position.X
    y = Player.Position.Y
    count = 0
    while x != x1 or y != y1:
        count += 1
        if count > 3 or abs(x-x1)>1 or abs(y-y1)>1:
            return(False)

        if x1 > x:
            if y1 < y:
                Player.Run('Right',False)
            elif y1 == y:
                Player.Run('East',False)
            elif y1 > y:
                Player.Run('Down',False)
        elif x1 == x:
            if y1 < y:
                Player.Run('North',False)
            elif y1 > y:
                Player.Run('South',False)
        elif x1 < x:
            if y1 < y:
                Player.Run('Up',False)
            elif y1 == y:
                Player.Run('West',False)
            elif y1 > y:
                Player.Run('Left',False) 
        Misc.Pause(50)
        x = Player.Position.X
        y = Player.Position.Y  
               
    return(True)

def autorun(points):
    global autorunCount
    # Spells.Interrupt()
    mx = points[0]
    my = points[1]
    list = getPath(mx, my)
    autorunCount += 1
    if list:
        if len(list) > 3:
            Misc.SendMessage('autorun ', 25)
            for l in list:
                onestep(l.X,l.Y)
                dw = onestep(l.X,l.Y)
                if not dw:
                    break
            if not dw and autorunCount < 4:
                autorun(points)
        else:
            Misc.SendMessage('goto(points) '+ str(mx) + '  ' + str(my) , 25)
            goto(points)

def runPathList(path):
    if path:
        for l in path:
            onestep(l.X,l.Y)
            dw = onestep(l.X,l.Y)
            if not dw:
                break

#检测需要使用的寻路方式
def run(points):
    mx = points[0]
    my = points[1]
    list = getPath(mx, my)
    if len(list) > 3:
        autorun(points)
    else:
        Misc.SendMessage('goto(points) '+ str(mx) + '  ' + str(my) , 25)
        goto(points)

#服务器寻路到指定点
def goto(points):
    # checkWeaponLayer()
    p = PathFinding.Route()
    p.X = points[0]
    p.Y = points[1]
    p.StopIfStuck = True
    # p.MaxRetry = 0
    p.IgnoreMobile = True 
    isReach = PathFinding.Go(p)
    # Misc.Pause(100)
    return isReach
#将服务器路径拆分多个节点寻路到指定点
def gotoByFindPath(points, isCheckEnemy = False, isUseRun = True):
    while Player.Position.X !=points[0] or Player.Position.Y != points[1] :
            # Misc.SendMessage('gotoByFindPath ', 25)
            t = findboss()
            if (not t is None and isCheckEnemy): 
                # Misc.SendMessage('gotoByFindPath getNearestEnemy is not None', 25)
                return False
            tileList = getPath(points[0], points[1])
            if tileList is None or len(tileList) == 0:
                return True
            # Player.PathFindTo(tileList[0].X,tileList[0].Y,0)
            if len(tileList) > 2:
                if isUseRun:
                    autorun([tileList[2].X,tileList[2].Y])
                else:
                    goto([tileList[2].X,tileList[2].Y])
            else:
                if isUseRun:
                    autorun([tileList[0].X,tileList[0].Y])
                else:
                    goto([tileList[0].X,tileList[0].Y])
            Misc.Pause(10)
    return True

#必 须 走 到 指 定 地 点
def gotoBySync(points, isCheckEnemy = False, isUseRun = True):
    if points:
        while Player.Position.X != points[0] or Player.Position.Y != points[1] :
                # Misc.SendMessage('gotoByFindPath ', 25)
            t = findboss()
            if (not t is None and isCheckEnemy): 
                # Misc.SendMessage('gotoByFindPath getNearestEnemy is not None', 25)
                return False
            if isUseRun:
                autorun(points)
            else:
                goto(points)
            Misc.Pause(50)
    return True

#释 放 鬼 形 魔 法
def changeWraithForm():
    Spells.Interrupt()
    Misc.Pause(200)
    Spells.CastNecro("Wraith Form")
    Misc.Pause(2500)

autorunCount = 0
#根 据 传 入 的 节 点 寻 路，并 在 到 达 每 个 节 点 时 检 测 周 围 是 否 有 敌 人 ，有 就 攻 击
def gotoWithCheckEnemy(points,loop = False,reverse = False,needSlowDown = False, changeForm = True, checkPosition = True):
    global pathStep
    global autorunCount
    # autorunCount = 0
    t = findboss()
    if t is None:
        #检测是否鬼形
        if changeForm and not isHuman():
            changeWraithForm()
        if usePet > 0:
            petcome()
        Misc.Pause(200)
        if pathStep >= len(points) or pathStep < 0:
            if loop:
                pathStep = 0
                Misc.Pause(300)
            else:
                return True
        Misc.SendMessage('go point '+ str(pathStep)+str(points[pathStep]) , 25)
        pathPoints = getPath(points[pathStep][0], points[pathStep][1])
        # Misc.SendMessage('pathPoints len '+ str(len(pathPoints)) , 25)
        if needSlowDown and pathPoints is not None and len(pathPoints) > 7:
            Misc.SendMessage('needSlowDown '+ str(pathPoints[len(pathPoints) - 6].X) + '  ' + str(pathPoints[len(pathPoints) - 6].Y) , 25)
            autorun([pathPoints[len(pathPoints) - 6].X, pathPoints[len(pathPoints) - 6].Y])
        elif pathPoints is not None and len(pathPoints) > 4:
            autorun([pathPoints[len(pathPoints) - 1].X, pathPoints[len(pathPoints) - 1].Y])
        else:
            autorun(points[pathStep])
        if checkPosition and (Player.Position.X != points[pathStep][0] or Player.Position.Y != points[pathStep][1]) and autorunCount < 5:
            autorunCount += 1
            return False
        if reverse:
            pathStep -= 1
        else:
            pathStep += 1
        Misc.Pause(100)
    else:
        # magicHealing()
        attackEnemy()
    return False


#根 据 传 入 的 节 点 寻 路 不 攻 击 附 近 的 敌 人 
def gotoTargetByPoints(points, loop = False, reverse = False):
    petcome()
    global pathStep
    if pathStep >= len(points) or pathStep < 0:
        if loop:
            pathStep = 0
            # Misc.Pause(300)
        else:
            return True
    Misc.SendMessage('go point '+ str(pathStep)+str(points[pathStep]) , 25)
    autorun(points[pathStep])
    if (Player.Position.X != points[pathStep][0] or Player.Position.Y != points[pathStep][1]):
        return False
    if reverse:
        pathStep -= 1
    else:
        pathStep += 1
    return False
followCount = 0
#4号 房 巡 逻
def room4GoRound(points,loop = False,reverse = False):
    global pathStep
    global autorunCount
    global boss4State
    global tick
    global followCount
    # autorunCount = 0
    if pathStep > 0 and isBossDead():
        return
    t = findboss()
    p = Mobiles.FindBySerial(petid)
    if not t:
        if boss4State == 1:
            boss4State = 2
            Misc.Pause(2000)
    # Misc.SendMessage('room4GoRound 1', 25)
    t = findboss()
    if t is None and boss4State == 2 and p and Player.DistanceTo(p) >= 2:
        Misc.SendMessage('room4GoRound 2', 25)
        gotoBySync([p.Position.X, p.Position.Y])
        # if isReach:
        DetectFourBoss(ZouWei()) 
        Misc.Pause(1000)
        for i in range(8):
            if Player.LowerReagentCost >= 99 :
                if necromancySkill > 60:
                    Spells.CastNecro("Wither")
                else:
                    Spells.CastNecro("Wither")
            else:
                Spells.CastChivalry('Holy Light')
            Misc.Pause(3000)
            if findboss():
                boss4State = 3
                return True
    elif not isBossDead() and t is None and pathStep < len(points):
        Misc.SendMessage('room4GoRound 3', 25)
        # Player.ChatSay(0,"all come")
        #检测是否鬼形
        # if changeForm and not isHuman():
        #     changeWraithForm()
        if pathStep >= len(points) or pathStep < 0:
            if loop:
                pathStep = 0
                Misc.Pause(300)
            else:
                return True
        autorun(points[pathStep])
        if (Player.Position.X != points[pathStep][0] or Player.Position.Y != points[pathStep][1]) and autorunCount < 5:
            autorunCount += 1
            return False
        if reverse:
            pathStep -= 1
        else:
            pathStep += 1
        Misc.Pause(100)
    elif t is None and pathStep >= len(points) and boss4State == 2:
        Misc.SendMessage('room4GoRound 4', 25)
        room4FindBoss(room4FindBossPoint)
    else:
        if boss4State == 0:
            boss4State = 1
            followCount = 0
        magicHealing()
        Misc.SendMessage('room4GoRound 5', 25)
        #满血就先荣誉一下
        if t and t.Hits == t.HitsMax:
            Player.InvokeVirtue('Honor')
            Target.WaitForTarget(3000, True)
            Target.TargetExecute(t)
            Misc.Pause(600)
        # Misc.SendMessage('room4GoRound 6', 25)
        if usePet == 2 and Player.Mount is not None:
            Mobiles.UseMobile(Player.Serial)
            Misc.Pause(200)
        # Misc.SendMessage('room4GoRound 7', 25)
        if boss4State == 1:
            if followCount < 4:
                if Timer.Check('room4GoRoundTime') is False:
                    petFollowTarget(t)
                    followCount += 1
                    Timer.Create('room4GoRoundTime', 6 * 1000)
        else:
            petkill(t)
        # Misc.SendMessage('room4GoRound 8', 25)
        playerkill(t)
        # Misc.SendMessage('room4GoRound 9', 25)
        Misc.Pause(100)
    return False


#找 到 附 近 的 物 品
def getNearItems():
    itemList = []
    ft = Items.Filter()
    find = List[int]([0x0E76])
    # ft.Graphics = find
    # ft.Name = 'a bag of sending' 
    # ft.OnGround = 0
    ft.RangeMin = -1
    ft.RangeMax = 10
    itemList = Items.ApplyFilter(ft)
    Misc.SendMessage('len(itemList) ' + str(len(itemList)),255)
    # senderBag = Items.FindBySerial(senderBagSerial)
    if len(itemList) > 0:
        for itm in itemList:
             Misc.SendMessage('itm ' + str(itm.Name),255)
    return itemList
    

#找 到 最 近 的 敌 人
def getNearestEnemy(RangeMax = 16):
    fil = Mobiles.Filter()
    # fil.Enabled = True
    fil.RangeMin = -1
    fil.RangeMax = RangeMax
    fil.CheckLineOfSight = True
    fil.Notorieties = List[Byte](bytes([3,4,5,6]))
    enemies = Mobiles.ApplyFilter(fil)
    # Misc.SendMessage('enemies '+ str(len(enemies)), 25)
    # for e in enemies:
    #     Misc.SendMessage('e.Name '+ str(e.Name), 25)
    t = Mobiles.Select(enemies,'Nearest')
    return t

#获 取 加 血 目 标 列 表
def getTargetList(targetRange, RangeMax):
    if targetRange > 1:
        fil = Mobiles.Filter()
        fil.Enabled = True
        fil.RangeMin = -1
        fil.RangeMax = RangeMax
        if targetRange == 2:
            fil.Friend = 1
        elif targetRange == 3:
            fil.Notorieties = List[Byte](bytes([1,2]))
        enemies = Mobiles.ApplyFilter(fil)
        # t = Mobiles.Select(enemies,'Nearest')
        return enemies
    return None

#绷 带 加 血 0无 加 血 1自 己 2别 人
def bandageHealing():
    #如果不使用绷带或者绷带技能小于20，就不执行
    if useBandage == 0 or Player.IsGhost or (healingSkill < 25 and veterinarySkill < 25):
        return 0
    # Misc.SendMessage('doBandageHealing 2 ' + str(healingSkill) + ' ' + str(veterinarySkill), 33)
    bandagecount = Items.ContainerCount(Player.Backpack.Serial,0x0E21,-1,True)
    
    #bandage = Items.FindByID(0x0E21,-1,Player.Backpack.Serial)
    if bandagecount > 0:
    #if bandage is not None:
        # pet = Mobiles.FindBySerial(petid)
        pet = getWeakestPet()
        #＊自己回复、自己解毒 ＝「１１－（DEX÷２０）」秒
        #＊他人回复、他人解毒＝「４－（DEX÷６０）」秒
        # selfTime = int((11 - Player.Dex / 20 + 1) * 1000)
        # otherTime = int((4 - Player.Dex / 60 + 1) * 1000)
        tar = None
        # Misc.SendMessage('绷带加血自己1 ' + str(selfTime) + '   ' + str(otherTime), 33)
        if useBandage == 1:
            tar = pet
        elif useBandage > 1:
            # Misc.SendMessage('绷带加血自己2 ', 33)
            targets = getTargetList(useBandage, 2)
            if targets is not None and len(targets) > 0:
                # Misc.SendMessage('绷带加血自己3 ' + str(len(targets)), 33)
                tar = Mobiles.Select(targets,'Weakest')
                # Misc.SendMessage('绷带加血 ' + tar.Name, 33)
        # if tar:
            # Misc.SendMessage('doBandageHealing 3' + tar.Name + '  ' + str(isCanUseBandage(tar)), 33)
        # else:
        #     Misc.SendMessage('doBandageHealing Target is None', 33)
        if healingSkill >= 25 and Player.Hits < Player.HitsMax * selflow:
            Misc.SendMessage('绷带加血自己 ', 33)
            Items.UseItemByID(0x0E21,-1)
            #Items.UseItem(bandage)
            Target.WaitForTarget(5000,True)
            Target.Self()
            # Misc.Pause(selfTime)
            return 1
        elif tar and isCanUseBandage(tar) and tar.Hits < tar.HitsMax * otherlow:
            Misc.SendMessage('绷带加血 别人' , 33)
            Items.UseItemByID(0x0E21,-1)
            #Items.UseItem(bandage)
            Target.WaitForTarget(5000,True)
            Target.TargetExecute(tar)
            # Misc.Pause(otherTime)
            if tar.IsHuman:
                return 2
            else:
                return 3
    return 0

#获 取 最 虚 弱 的 宠 物
def getWeakestPet():
    weakestPet = None
    if not petList is None and len(petList) > 0:
        petHp = 999999999
        for petid in petList:
            pet = Mobiles.FindBySerial(petid)
            if pet is None:
                continue
            if pet.Poisoned:
                return pet
            if pet.Hits < petHp:
                petHp = pet.Hits
                weakestPet = pet
    return weakestPet

#魔 法 或 者 骑 士 精 神、武 士 道 加 血
def magicHealing():
    # Misc.SendMessage('magicHealing ' + str(useMagicHeal == 0 or useSkill == 0 or Player.IsGhost or isAtPoison), 33)
    # Misc.SendMessage('magicHealing 1' , 33)
    if useMagicHeal == 0 or useSkill == 0 or Player.IsGhost or Player.Mana < 10:
        return 0
    # Misc.SendMessage('magicHealing 2' , 33)
    global isRecoverHP
    pet = getWeakestPet()
    tar = None
    if useMagicHeal == 1:
        tar = pet
    elif useMagicHeal > 1:
        targets = getTargetList(useMagicHeal, 7)
        if targets and len(targets) > 0:
            tar = Mobiles.Select(targets,'Weakest')
    if isRecoverHP and Player.Hits > Player.HitsMax * 0.90 and tar and tar.Hits > tar.HitsMax * 0.90:
        isRecoverHP = False
    # Misc.SendMessage('magicHealing ' + str(3), 33)
    if Player.Poisoned:
        Misc.SendMessage('魔法解毒自己 ', 33)
        if useSkill == 2:
            Spells.CastMagery("Arch Cure")
        else:
            Spells.CastChivalry("Cleanse by Fire")
        Target.WaitForTarget(5000,True)
        # Target.Self()
        Target.TargetExecute(Player.Serial)
        Misc.Pause(800)
        # return 600
    elif Player.Hits < Player.HitsMax * selflowMig or (isRecoverHP and Player.Hits < Player.HitsMax * 0.90):
        isRecoverHP = True
        Misc.SendMessage('魔法加血自己 ', 33)
        #先用武士道的自信
        # if bushidoSkill > 40 and not Player.BuffsExist('Confidence'):
        #     Spells.CastBushido('Confidence')
        #     Misc.Pause(1500)
        if useSkill == 2:
            Spells.CastMagery("Greater Heal")
        else:
            Spells.CastChivalry("Close Wounds")
        Target.WaitForTarget(5000, True)
        # Target.Self()
        Target.TargetExecute(Player.Serial)
        Misc.Pause(1800)
        # return 1800
    elif tar and tar.Poisoned:
        Misc.SendMessage('魔法解毒别人 ', 33)
        if useSkill == 2:
            Spells.CastMagery("Arch Cure")
        else:
            Spells.CastChivalry("Cleanse by Fire")
        Target.WaitForTarget(5000,True)
        Target.TargetExecute(tar)
        Misc.Pause(800)
        # return 600
    elif tar and tar.Hits > 0 and (tar.Hits < tar.HitsMax * otherlowMig or (isRecoverHP and tar.Hits < tar.HitsMax * 0.90)):
        isRecoverHP = True
        Misc.SendMessage('魔法加血别人 ' + tar.Name, 33)
        if useSkill == 2:
            Spells.CastMagery("Greater Heal")
        else:
            Spells.CastChivalry("Close Wounds")
        Target.WaitForTarget(5000, True)
        Target.TargetExecute(tar)    
        Misc.Pause(1800)
        # return 1800

def doBandageHealing():
    if Timer.Check('doBandageHealingTime') is False:
        # Misc.SendMessage('doBandageHealing 1', 33)
        type = bandageHealing()
        time = 100
        if type == 1:
            time = int((11 - Player.Dex / 20 + 1) * 1000)
        elif type == 2:
            time = int((4 - Player.Dex / 60 + 1) * 1000)
        elif type == 3:
            time = 2200
        
        Timer.Create('doBandageHealingTime', time)
        

def doMagicHealing():
    if Timer.Check('doMagicTime') is False:
        # Misc.SendMessage('doBandageHealing 1', 33)
        pauseTime = magicHealing()
        Timer.Create('doMagicTime', pauseTime)

def doCheckAttackBuff():
    if Timer.Check('doMagicTime') is False:
        # Misc.SendMessage('doBandageHealing 1', 33)
        checkAttackBuff()
        Timer.Create('doMagicTime', 0)

#检 测 金 钱 数 量 ，达 到 数 量 送 回 银 行
def checkGold():
    gold = Items.FindByID(0x0EED,0,Player.Backpack.Serial)
    # if gold is not None:
    #     Misc.SendMessage('gold is None ' + str(gold.Amount),255)
    if gold is not None and gold.Amount > 57000:
        # powder = Items.FindByID(gold,-1,Player.Backpack.Serial)
        itemList = []
        ft = Items.Filter()
        find = List[int]([0x0E76])
        ft.Graphics = find
        # ft.Name = 'a bag of sending' 
        ft.OnGround = 0
        # ft.RangeMin = 0
        # ft.RangeMax = 1
        itemList = Items.ApplyFilter(ft)
        # Misc.SendMessage('len(itemList) ' + str(len(itemList)),255)
        # senderBag = Items.FindBySerial(senderBagSerial)
        if len(itemList) > 0:
            for itm in itemList:
                # Items.GetPropStringByIndex(apple,0)
                # Misc.SendMessage('name ' + Items.GetPropStringByIndex(itm,0),255)
                name = Items.GetPropStringByIndex(itm,0)
                charges = Items.GetPropStringByIndex(itm,2)
                charges = charges.replace('charges:', '')
                if charges is not None:
                    if 'sending' in name:
                        # Misc.SendMessage('charges ' + str(charges),255)
                        if int(charges) > 0:
                            Items.UseItem(itm)
                            Target.WaitForTarget(5000,True)
                            Target.TargetExecute(gold)
                            Misc.Pause(800)
                            break

#是 否 需 要 逃 命
def checkNeedRunAway():
    if Player.Hits < Player.HitsMax * keepAwayFlow:
        tart = getNearestEnemy(2)
        if tart is not None:
            keepAwayFromTarget(tart)
#保 持 与 指 定 对 象 的 距 离
def keepAwayFromTarget(target, distance = 3):
    if target is not None:
        # distan = Player.DistanceTo(target)
        keepDis = distance
        # if distan < 3:
        # Spells.Interrupt()
        if Player.Position.X == target.Position.X:# 敌人在同一Y轴上
            if Player.Position.Y > target.Position.Y:   #敌人在正下方
                if isTargetReachable(Player.Position.X, Player.Position.Y + keepDis):
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y):
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y):
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
                else:
                    autorun([Player.Position.X , Player.Position.Y] - keepDis)
            else:   #敌人在正上方
                if isTargetReachable(Player.Position.X, Player.Position.Y - keepDis):
                    autorun([Player.Position.X, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y):
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y):
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
                else:
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
        elif Player.Position.X > target.Position.X: # 敌人在左侧
            if Player.Position.Y > target.Position.Y:   #敌人在左下方
                if isTargetReachable(Player.Position.X + keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y):
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X, Player.Position.Y + keepDis):
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
                else:
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
            else:   #敌人在左上方
                if isTargetReachable(Player.Position.X + keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y):
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X, Player.Position.Y - keepDis):
                    autorun([Player.Position.X, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
                else:
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
        elif Player.Position.X < target.Position.X: # 敌人在右侧
            if Player.Position.Y > target.Position.Y:   #敌人在右下方
                if isTargetReachable(Player.Position.X - keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y):
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X, Player.Position.Y + keepDis):
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
                else:
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
            else:   #敌人在右上方
                if isTargetReachable(Player.Position.X - keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y):
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X, Player.Position.Y - keepDis):
                    autorun([Player.Position.X, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
                else:
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
        elif Player.Position.Y == target.Position.Y: # 敌人在同一X轴上
            if Player.Position.X > target.Position.X:   #敌人在左方
                if isTargetReachable(Player.Position.X + keepDis, Player.Position.Y):
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X + keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X + keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X, Player.Position.Y - keepDis):
                    autorun([Player.Position.X, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X, Player.Position.Y + keepDis):
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
                else:
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
            else:   #敌人在右方
                if isTargetReachable(Player.Position.X - keepDis, Player.Position.Y):
                    autorun([Player.Position.X - keepDis, Player.Position.Y])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y - keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y - keepDis])
                elif isTargetReachable(Player.Position.X - keepDis, Player.Position.Y + keepDis):
                    autorun([Player.Position.X - keepDis, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X, Player.Position.Y + keepDis):
                    autorun([Player.Position.X, Player.Position.Y + keepDis])
                elif isTargetReachable(Player.Position.X, Player.Position.Y - keepDis):
                    autorun([Player.Position.X, Player.Position.Y - keepDis])
                else:
                    autorun([Player.Position.X + keepDis, Player.Position.Y])
        Misc.Pause(100)
        
#在 宠 物 后 面 攻 击
def getBehindPetPosition():
    p = Mobiles.FindBySerial(petid)
    if not p:
        return None
    direc = p.Direction
    x = 0
    y = 0
    if direc == 'Down':
        x = p.Position.X - 1
        y = p.Position.Y - 1
    elif direc == 'up':
        x = p.Position.X + 1
        y = p.Position.Y + 1
    elif direc == 'Right':
        x = p.Position.X - 1
        y = p.Position.Y + 1
    elif direc == 'Left':
        x = p.Position.X + 1
        y = p.Position.Y - 1
    elif direc == 'North':
        x = p.Position.X
        y = p.Position.Y + 1
    elif direc == 'South':
        x = p.Position.X
        y = p.Position.Y - 1
    elif direc == 'East':
        x = p.Position.X - 1
        y = p.Position.Y
    elif direc == 'West':
        x = p.Position.X + 1
        y = p.Position.Y
    else:
        x = p.Position.X
        y = p.Position.Y
    return [x,y]

#走 到 宠 物 后 面
def gotoBehindPetPosition():
    pos = getBehindPetPosition()
    if pos:
        goto(pos)

#指 定 坐 标 是 否 可 以 到 达
def isTargetReachable(x, y):
    tileList = getPath(x, y)
    if tileList is not None and len(tileList) > 0:
        return True
    return False

#已 拾 取 的 尸 体 id 列 表
lootedCorpsesID = []
#指 定 尸 体 id是 否 已 拾 取 过
def isTargetCropseLooted(corpsesSerial):
    return lootedCorpsesID.count(corpsesSerial) > 0
#添 加 拾 取 过 的 尸 体 id
def appendLootedCropse(corpsesSerial):
    lootedCorpsesID.append(corpsesSerial)

#添 加 已 打 开 的 尸 体
def openCorpses():
    fBones = Items.Filter()
    fBones.OnGround = 1
    fBones.RangeMin = -1
    fBones.RangeMax = 3
    fBones.IsCorpse = 1
    fBones.Movable = False
    # fBones.Graphics = BList
    BonesList = Items.ApplyFilter(fBones)
    # Misc.SendMessage('hideCorpses len(BonesList): ' + str(len(BonesList)),88)
    isOpen = False
    if len(BonesList) > 0:
        for bone in BonesList:
            try:
                if Player.DistanceTo(bone) <= 2:
                    if isTargetCropseLooted(bone.Serial):
                        continue
                    # Items.WaitForContents(bone, 5000)
                    if len(bone.Contains) > 0:
                        Misc.SendMessage('appendLootedCropse len(bone.Contains): ' + str(len(lootedCorpsesID)),88)
                        appendLootedCropse(bone.Serial)
                        isOpen = True
                    Misc.Pause(100)
            except Exception as e:
                Misc.SendMessage('异 常: ' + str(e),88)
    return isOpen

#隐 藏 附 近 已 拾 取 的 尸 体
def hideCorpses():
    fBones = Items.Filter()
    fBones.OnGround = 1
    fBones.RangeMin = -1
    fBones.RangeMax = 2
    fBones.IsCorpse = 1
    fBones.Movable = False
    # fBones.Graphics = BList
    BonesList = Items.ApplyFilter(fBones)
    # Misc.SendMessage('hideCorpses len(BonesList): ' + str(len(BonesList)),88)
    if len(BonesList) > 0:
        # Misc.SendMessage('hideCorpses len(BonesList): ' + str(len(BonesList)),88)
        for bone in BonesList:
            try:
                if Player.DistanceTo(bone) <= 2:
                    if not isTargetCropseLooted(bone.Serial) or not bone.Visible:
                        continue
                    gold = Items.FindByID(0x0EED, -1, bone.Serial)
                    # Misc.Pause(100)
                    # Misc.SendMessage('hideCorpses len(bone.Contains): ' + str(len(bone.Contains)),88)
                    if gold is None:
                        # Misc.SendMessage('hideCorpses len(BonesList): ' + str(len(BonesList)),88)
                        Items.Hide(bone)
                    Misc.Pause(100)
                # else:
                #     Items.Hide(bone) 
            except Exception as e:
                Misc.SendMessage('异 常: ' + str(e),88)

#获 取 最 近 的 未 拾 取 的 怪 物 尸 体
def getNearestCorpse():
    fBones = Items.Filter()
    fBones.OnGround = 1
    fBones.RangeMin = -1
    fBones.RangeMax = 7
    fBones.IsCorpse = 1
    fBones.Movable = False
    # fBones.Graphics = BList
    BonesList = Items.ApplyFilter(fBones)
    if len(BonesList) > 0:
        nList = []
        for i in BonesList:
            if i.Visible and not isTargetCropseLooted(i.Serial):
                nList.append([i,i.DistanceTo(Mobiles.FindBySerial(Player.Serial))])
        if len(nList) > 0:
            nList.sort(key=lambda x: x[1], reverse = False)
            return nList[0][0]
    return None

#走 近 附 近 的 怪 物 尸 体
def gotoNearestCorpse():
    corpse = getNearestCorpse()
    if corpse is None:
        return False
    isGoto = gotoByFindPath([corpse.Position.X, corpse.Position.Y], True)
    return isGoto
#有 检 测 毒 液 功 能 的 暂 停 ，如 果 有 毒 液 就 停 止 暂 停 ，暂 停 时 间 100的 倍 数
def pauseWithCheck(delay):
    tick = int(delay / 100)
    step = 0
    while step < tick:
        step += 1
        Misc.Pause(100)


#通 过 门 的 颜 色 判 断 房 间 的 状 态  0-未 知 1-未 开 启 2-已 激 活 3-已 打 过
def checkRoomState():
    fil = Items.Filter()
    fil.OnGround = 1
    # fil.RangeMin = -1
    # fil.RangeMax = 10
    # fil.IsDoor = 1
    fil.Graphics = List[int]([
        0x067F, 0x067D, 0x067E, 0x0680, 
        0x0675, 0x0676, 0x0677, 0x0678,
        ])
    itemList = Items.ApplyFilter(fil)
    state = 0
    # Misc.SendMessage('len(itemList) ' + str(len(itemList)),88)
    if len(itemList) > 0:
        for i in itemList:
            # Misc.SendMessage('i.Hue ' + str(i.Hue),88)
            if i.Hue == 0x0676:
                state = 2
            elif i.Hue == 0x0455:
                state = 3
            elif i.Hue == 0x0000:
                state = 1
    Misc.SendMessage('checkRoomState ' + str(state))
    return state
#检 测 当 前 打 到 第 几 门 了
def checkRoomState():
    fil = Items.Filter()
    fil.OnGround = 1
    # fil.RangeMin = -1
    # fil.RangeMax = 10
    # fil.IsDoor = 1
    fil.Graphics = List[int]([
        0x067F, 0x067D, 0x067E, 0x0680, 
        0x0675, 0x0676, 0x0677, 0x0678,
        ])
    itemList = Items.ApplyFilter(fil)
    state = 0
    # Misc.SendMessage('len(itemList) ' + str(len(itemList)),88)
    if len(itemList) > 0:
        for i in itemList:
            # Misc.SendMessage('i.Hue ' + str(i.Hue),88)
            if i.Hue == 0x0676:
                state = 2
            elif i.Hue == 0x0455:
                state = 3
            elif i.Hue == 0x0000:
                state = 1
    Misc.SendMessage('checkRoomState ' + str(state))
    return state

#通 过 附 近 敌 人 搜 索 和 地 上 陷 阱 判 断 boss是 否 已 经 死 亡
def isBossDead():
    t = findboss()
    if t is not None:
        return False
    fil = Items.Filter()
    fil.OnGround = 1
    # fil.RangeMin = -1
    # fil.RangeMax = 25
    # fil.IsDoor = 1
    fil.Graphics = List[int]([0x1125,0x1126,0x1127,0x1128,0x1129,0x112A,0x113A,0x113B,0x113C,0x113D,
    0x113E,0x119A,0x119B,0x119C,0x119D,0x119E,0x119F,0x11A0,0x11A1,0x11A2,0x11A3,0x11A4,0x11A5,0x11A9,
    0x11AA,0x11AB,0x11AC,0x11AD,0x11AE,0x11F,0x11B0,0x11B1,0x1145,0x1146,0x1147,0x1148,0x1149,0x114A,0x1B71])
    itemList = Items.ApplyFilter(fil)
    if itemList and len(itemList) > 0:
        return False
    return True
#设 置 当 前 任 务 状 态
def setState(state, step = 0):
    global taskState
    global pathStep
    global boss4State
    global autorunCount
    if state != taskState:
        taskState = state
        pathStep = step
        Misc.SendMessage('setState ' + str(state))
        checkMagicSlayerBook()
    boss4State = 0
    autorunCount = 0
#第 四 房 间 boss隐 身 后 转 圈 炸 boss
findBossStep = 0
def room4FindBoss(points):
    global findBossStep
    if findBossStep >= len(points):
        findBossStep = 0
    # Misc.SendMessage('go point '+ str(findBossStep)+str(points[findBossStep]) , 25)
    gotoPointWithAOE(points[findBossStep])
    if Player.Position.X != points[findBossStep][0] or Player.Position.Y != points[findBossStep][1]:
        return
    findBossStep += 1
    Misc.Pause(300)
#第 四 房 间 boss隐 身 后 依 靠 宠 物 跟 随 寻 找 boss
def room4FindBossByPet():
    isReach = False
    if petList is not None:
        for petid in petList:
            p = Mobiles.FindBySerial(petid)
            if p is not None and Mobiles.GetPropValue(petid,'guard') == False:
                isReach = goto([p.Position.X, p.Position.Y])
                if isReach:
                    break
        if isReach:
            if Player.LowerReagentCost == 100 :
                if necromancySkill > 60:
                    Spells.CastNecro("Wither")
                #else:
                    #Spells.CastNecro("Wither")
            else:
                Spells.CastChivalry('Holy Light')
            Misc.Pause(200)
    return isReach

#边 走 边 炸
def gotoPointWithAOE(points):
    while Player.Position.X !=points[0] or Player.Position.Y != points[1] :
        if Player.Mana < 20:
            return
        tileList = getPath(points[0], points[1])
        if tileList is None or len(tileList) == 0:
            return
        # Player.PathFindTo(tileList[0].X,tileList[0].Y,0)
        if len(tileList) > 3:
            goto([tileList[3].X,tileList[3].Y])
        else:
            goto([points[0],points[1]])
        # Misc.Pause(100)
        if Player.LowerReagentCost == 100 :
            if necromancySkill > 60:
                Spells.CastNecro("Wither")
            else:
                Spells.CastNecro("Wither")
        else:
            Spells.CastChivalry('Holy Light')
        Misc.Pause(2000)
        if isBossDead():
            return

#剔骨
BList = List[int]([0xECA,0xECB,0xECC,0xECD,0xECE,0xECF,0xED0,0xED1,0xED2])
def BonesCut():
    global BladesId
    cut = Items.FindBySerial(BladesId)
    if cut is None:
        BladesId = 0
        setBlades()
    if cut is not None:
        fBones = Items.Filter()
        fBones.OnGround = 1
        fBones.RangeMin = -1
        fBones.RangeMax = 10
        fBones.IsCorpse = 1
        fBones.Movable = False
        fBones.Graphics = BList
        BonesList = Items.ApplyFilter(fBones)
        if len(BonesList) > 0:
            for bone in BonesList:
                try:
                    Items.WaitForProps(bone,50)
                    if Items.GetPropValue(bone,'Bones'):
                        Items.UseItem(cut)
                        Target.WaitForTarget(2000,True)
                        Target.TargetExecute(bone)
                        Misc.Pause(50)
                except Exception as e:
                    Misc.SendMessage('异 常: ' + str(e),88)

backpackOldLen = 0
#检 测 是 否 获 取 doom 神 器
def checkHaveNewArtifact():
    global backpackOldLen
    backpackItems = Player.Backpack.Contains
    # Misc.SendMessage('len(backpackItems) ' + str(len(backpackItems)) + '  backpackOldLen ' + str(backpackOldLen), 33)
    # if backpackOldLen != len(backpackItems):
    #     backpackOldLen = len(backpackItems)
    for item in backpackItems:
        name = Items.GetPropStringByIndex(item,0)
        if not 'Insured' in Items.GetPropStringByIndex(item, 1) and (insuranceDoomArtifacts.count(name) > 0 or insuranceDoomArtifacts.count(name.title()) > 0):
            # Misc.SendMessage('item ' + str(name), 33)
            # if not 'Insured' in Items.GetPropStringByIndex(item, 1):
            Misc.SendMessage('item ' + str(name), 33)
            # Misc.SendMessage('item prop1  ' + str(Items.GetPropStringByIndex(item,1)), 33)
            inserancecItem(item)
            Misc.Pause(300)
            Target.Cancel()
#保 险 指 定 物 品
def inserancecItem(item):
    # isOK = False
    # for i in range(5):
    #     isOK = Misc.UseContextMenu(Player.Serial, 'Toggle Item Insurance', 5000)
    #     Misc.Pause(100)
    #     if isOK:
    #         break
    # if isOK:
    #     Misc.SendMessage('Toggle Item Insurance' + item.Name, 33)
    #     Target.TargetExecute(item)
    Misc.WaitForContext(Player.Serial, 1000)
    Misc.ContextReply(Player.Serial, 'Toggle Item Insurance')
    Target.WaitForTarget(1000, True)
    Target.TargetExecute(item)

#寻 找 boss
def findboss():
    efilter = Mobiles.Filter()
    efilter.Enabled = True
    # efilter.CheckLineOfSite = True
    efilter.Bodies = List[int]([0x0139,0x013B,0x0132,0x0137,0x0138,0x013E])
    efilter.Notorieties = List[Byte](bytes([3,4,5,6]))

    bosslist = Mobiles.ApplyFilter(efilter)
    if bosslist:
        boss = Mobiles.Select(bosslist,'Nearest')
        return boss
    return None 

#宠 物 跟 随 目 标
def petFollowTarget(target):
    if target and petList:
        # Spells.Interrupt()
        # for petid in petList:
        #     p = Mobiles.FindBySerial(petid)
        #     try:
        #         Misc.WaitForContext(p, 2000)
        #         Misc.ContextReply(p, 'Command: Follow')
        #         Target.WaitForTarget(2000, False)
        #         Target.TargetExecute(target)
        #     except Exception as e:
        #         Misc.SendMessage('异 常: ' + str(e),88)
        Player.ChatSay(53,"all follow")
        Target.WaitForTarget(1000, True)
        Target.TargetExecute(target)

#黑 爹 是 否 在 远 程 可 攻 击 区 域
def isDfInPositionArea(df):
    if df:
        return (df.Position.X >= 446 and df.Position.X <= 452 and df.Position.Y >= 419 and df.Position.Y <= 424)
    return False

#黑 爹 是 否 在 卡 位 452 419 452, 420
def isDfInPosition(df):
    if df:  
        return (df.Position.X == 452 and df.Position.Y == 419) or (df.Position.X == 452 and df.Position.Y == 420) or (df.Position.X == 451 and df.Position.Y == 420)
    return False
#黑 爹 是 否 在 玩 家 的 卡 位 453 419 ,454 419
def isDfInPlayerPosition(df):
    if df:  
        return (df.Position.X == 453 and df.Position.Y == 419) or (df.Position.X == 454 and df.Position.Y == 419)
    return False
#自 己 是 否 在 卡 位 453 419
def isSelfInPosition():
    return Player.Position.X == 453 and Player.Position.Y == 419

#自 己 是 否 在 卡 位 最 里 面 454 419
def isSelfInSafePosition():
    return Player.Position.X == 454 and Player.Position.Y == 419

#检 测 宠 物 是 否 在 卡 位
def isPetInPosition():
    global petid
    p = Mobiles.FindBySerial(petid)
    if p:
        return (p.Position.X == 453 or p.Position.Y == 419) or (p.Position.X == 452 or p.Position.Y == 419)

#检 测 宠 物 是 否 在 卡 位
def checkPetIsInPosition():
    global petid
    p = Mobiles.FindBySerial(petid)
    if usePet == 2 and p:
        if isSelfInPosition() and (p.Position.X != 453 or p.Position.Y != 419):
            if Player.DistanceTo(p) > 2:
                Player.ChatSay(33,"all come")
            else:
                if isHuman():
                    Mobiles.UseMobile(p)
                    Misc.Pause(300)
                    Mobiles.UseMobile(p)
        elif isSelfInSafePosition() and not ((p.Position.X == 453 and p.Position.Y == 419) or (p.Position.X == 454 and p.Position.Y == 419)):
            Player.ChatSay(55,"all come")

#是 否 需 要 往 卡 点 逃 命
def checkNeedRunAwayDF():
    if taskState == 2 and isDemise:
        if Player.Hits < Player.HitsMax * keepAwayFlow:
            df = findboss()
            pathList = PathFinding.GetPath(454, 419, True)
            if df and pathList and len(pathList) < 8 and not isDfInPlayerPosition(df):
            # if isPetInPosition():
                # Spells.Interrupt()
                autorun([454, 419])
                Misc.Pause(100)
                return True
            elif isSelfInSafePosition() and Player.DistanceTo(df) > 1:
                return True
            # elif
    return False

#指 定 角 色 是 否 是 自 己 的 宠 物
def isMyPet(target):
    if petList and target:
        for petid in petList:
            if target.Serial == petid:
                return True
    return False

#黑 爹 身 边 是 否 有 玩 家
def isDfAroundPlayer(df):
    if df:
        fil = Mobiles.Filter()
        fil.Enabled = True
        fil.IsHuman = True
        fil.Notorieties = List[Byte](bytes([1,2]))
        mobs = Mobiles.ApplyFilter(fil)
        if mobs:
            for mob in mobs:
                if mob.Serial != df.Serial and mob.DistanceTo(df) < 3:
                    Misc.SendMessage('mob ' + mob.Name, 255)
                    return True
    return False

#黑 爹 是 否 在 移 动
def isDFInMove(df):
    if df:
        global oldX
        global oldY
        if oldX == 0 and oldY == 0:
            oldX = df.Position.X
            oldY = df.Position.Y
            return True
        else:
            if oldX != df.Position.X or oldY != df.Position.Y:
                oldX = df.Position.X
                oldY = df.Position.Y
                return True
    return False


pullCount = 0
pullDFOutCount = 0
oldX = 0
oldY = 0
#打 黑 爹
def attackDF():
    if profession > 1:
        attackDFMagic()
    else:
        attackDFWarrior()
#法 系 打 df
def attackDFMagic():
    global pullCount
    global pullDFOutCount
    df = findboss()
    if not df:
        Misc.SendMessage('attackDF df is None', 255)
    # magicHealing()
    if Timer.Check('pullDFTime') is False:
        pullCount = 0
        Timer.Create('pullDFTime', 15 * 1000)
    if df and Player.Hits > Player.HitsMax * keepAwayFlow:
        if isDfInPlayerPosition(df) and pullCount < 4:#df是否在玩家的卡位
            Misc.SendMessage('df跑到了玩家的卡位', 255)
            # if Timer.Check('pullDFOutTime') is False:
            # if not isHuman():
            #     changeWraithForm()
            petcome()
            oldX2 = df.Position.X
            oldY2 = df.Position.Y
            # pullCount = 0
            # while pullCount < 4:
            if df and Player.DistanceTo(df) > 3:
                magicHealing()
            pullDF2Out()
            Misc.Pause(100)
            df = findboss()
            if not isDfInPosition(df):
                if oldX2 == df.Position.X and oldY2 == df.Position.Y:
                    pullCount += 1
        elif df and profession > 1 and not isSelfInSafePosition():
            Misc.SendMessage('自己不在安全位置', 255)
            # df = findboss()
            # if isPetInPosition():
                # Spells.Interrupt()
            gotoBySync([454, 419])
            if isHuman():
                changeWraithForm()
        elif isDfInPositionArea(df):
            Misc.SendMessage('攻击df', 255)
            checkPetIsInPosition()
            if df and Player.Hits > Player.HitsMax * keepAwayFlow and not isRecoverHP:
                # Misc.SendMessage('playerkill 1 ' , 25)
                honorTarget(df)
                Target.SetLast(df)
                Player.Attack(df)    
                # closeToTarget(df)
                if usePet > 0:
                    petkill(df)
                checkAttackBuff()
                if profession > 2:#法师
                    # Misc.SendMessage('playerkill 4 ' , 25)
                    magicAttack(df)      

#近 战 打 df
def attackDFWarrior():
    global pullCount
    global pullDFOutCount
    df = findboss()
    if not df:
        Misc.SendMessage('attackDF df is None', 255)
    # magicHealing()
    if Timer.Check('pullDFTime') is False:
        pullCount = 0
        Timer.Create('pullDFTime', 15 * 1000)
    if df and Player.Hits > Player.HitsMax * keepAwayFlow:
        if isDfInPlayerPosition(df) and pullCount < 4:#df是否在玩家的卡位
            Misc.SendMessage('df跑到了玩家的卡位', 255)
            # if Timer.Check('pullDFOutTime') is False:
            # if not isHuman():
            #     changeWraithForm()
            petcome()
            oldX2 = df.Position.X
            oldY2 = df.Position.Y
            # pullCount = 0
            # while pullCount < 4:
            if df and Player.DistanceTo(df) > 3:
                magicHealing()
            pullDF2Out()
            Misc.Pause(100)
            df = findboss()
            if not isDfInPosition(df):
                if oldX2 == df.Position.X and oldY2 == df.Position.Y:
                    pullCount += 1
        elif (profession == 1 and not isDfInPosition(df)):#df不在boss卡位 战士
            Misc.SendMessage('df不在boss卡位 战士', 255)
            Target.SetLast(df)
            Player.Attack(df)

            if not isDfAroundPlayer(df):
                if df and (Player.DistanceTo(df) < 6) or Player.Position.X < df.Position.X:
                    petcome()
                    gotoDFSafePosition()
                elif Player.DistanceTo(df) > 10:
                    pathList = PathFinding.GetPath(df.Position.X, df.Position.Y, True)
                    if pathList:
                        if pathList and len(pathList) > 8:
                            gotoBySync([pathList[7].X, pathList[7].Y])
                        # else:
                        #     runPathList(pathList)
            elif pullCount < 4:
                oldX2 = df.Position.X
                oldY2 = df.Position.Y
                pullDF2Position()
                Misc.Pause(100)
                df = findboss()
                if df and not isDfInPosition(df):
                    if oldX2 == df.Position.X and oldY2 == df.Position.Y:
                        pullCount += 1
            else:
                attackEnemy()
        elif df and profession == 1 and not isSelfInPosition(): #自己不在卡位
            Misc.SendMessage('自己不在卡位', 255)
            autorun([453, 419])
        # df = findboss()
        else:
            Misc.SendMessage('攻击df', 255)
            checkPetIsInPosition()
            attackEnemy()   

#往 df的 卡 位 上 走
def gotoDFSafePosition():
    pathList = PathFinding.GetPath(453, 419, True)
    if pathList:
        if pathList and len(pathList) > 10:
            gotoBySync([pathList[10].X, pathList[10].Y])
        else:
            runPathList(pathList)

#寻 找 黑 爹 并 把 黑 爹 拉 倒 卡 角 位 置 攻 击 0x013E 453, 419
def pullDF2Position():
    df = findboss()
    if df:
        Target.SetLast(df)
        Player.Attack(df)
        if not isDfInPosition(df):
            # if Player.DistanceTo(df) > 8:
            #     autorun([df.Position.X, df.Position.Y])
            # df = findboss()
            if df and Player.DistanceTo(df) < 6 or Player.DistanceTo(df) > 10:
                if not isSelfInPosition():
                    pathList = PathFinding.GetPath(453, 419, True)
                    if pathList:
                        if pathList and len(pathList) > 6:
                            autorun([pathList[5].X, pathList[5].Y])
                        else:
                            runPathList(pathList)
#把 黑 爹 拉 出 卡 角
def pullDF2Out():
    df = findboss()
    if df:
        Target.SetLast(df)
        Player.Attack(df)
        if isDfInPlayerPosition(df):
            if df and Player.DistanceTo(df) < 3 or Player.DistanceTo(df) > 8:
                pathList = PathFinding.GetPath(451, 419, True)
                if pathList:
                    if pathList and len(pathList) > 5:
                        autorun([pathList[4].X, pathList[4].Y])
                    else:
                        runPathList(pathList)
                    

#玩 家 是 否 是 人 型 状 态
def isHuman(target = Player):
    return target.MobileID == 0x025E or target.MobileID == 0x025D or target.MobileID == 0x0190 or target.MobileID == 0x0191
#是 否 可 以 使 用 绷 带 治 疗 
def isCanUseBandage(target):
    if target and hasattr(target, 'IsHuman'):
        if target.IsHuman and healingSkill > 25:
            return True
        if not target.IsHuman and veterinarySkill > 25:
            return True
    else:
        Misc.SendMessage('hasattr(target, isHuman)' ,88)
    return False


#五 芒 星 中 心 的 坐 标
floorPosotions = [
    (423, 430),
    (417, 426),
    (426, 422),
    (432, 430),
    (424, 439),
    (416, 435),
]
#当 前 开 启 的 房 间
def curboss():
    x = Player.Position.X
    y = Player.Position.Y
    if x < 415:
        x = 415
    elif x > 435:
        x = 435
    if y < 422:
        y = 422
    elif y > 439:
        y = 439

    # autorun([x,y])
    Misc.SendMessage('curboss x' + str(x) + ' y' + str(y),88)
    gotoBySync([x,y])
    
    fil = Items.Filter()
    fil.OnGround = 1
    fil.Graphics = List[int]([
        0x0FEA
        ])
    fil.Hues = List[int]([
        0x0676
        ])
    itemList = Items.ApplyFilter(fil)
    # Misc.SendMessage('len(itemList) ' + str(len(itemList)),88)
    if itemList and len(itemList) > 0:
        item = itemList[0]
        if item:
            for i in range(6):
                if floorPosotions[i] and item.Position.X == floorPosotions[i][0] and item.Position.Y == floorPosotions[i][1]:
                    return i
    return 0
#发 现 gm
def findGM():
    efilter = Mobiles.Filter()
    efilter.Enabled = True
    efilter.IsHuman = True
    efilter.Notorieties = List[Byte](bytes([1,2]))  
#    efilter.Bodies = List[Int32]([0x0053,0x001E,0x02D5,0x0049,0x0111,0x010B])    
    bosses = Mobiles.ApplyFilter(efilter) 
    if len(bosses)>0:
        for boss in bosses:
            name = Mobiles.GetPropStringByIndex(boss,0)
            if 'GM' in name.strip():
            #if name.strip() in bosslist:
                return(boss)
    else :
        return(False)

def BagItemsCounts(YSL):
    if len(Player.Backpack.Contains) > YSL:
        Misc.ScriptRun('包内物品进行保险.py')
        
    return len(Player.Backpack.Contains)    
        
#计 时 器
tick = 0
#main
def main():
    global taskState
    global pathStep
    global tick
    while True:
        #Misc.ScriptRun('包内物品进行保险.py')
        #BWPysl = len(Player.Backpack.Contains)
        #BWPysl0 = len(Player.Backpack.Contains)
        #BWPysl0 = BagItemsCounts(BWPysl)
        Misc.Pause(100)
        tick += 1
        boss = findGM()
        if Gumps.HasGump() and Gumps.CurrentGump() == 3279111667:
            Misc.Beep()
            Misc.Pause(6000)
        elif Player.IsGhost:
            Misc.Beep()
            continue
        elif boss:
            Misc.Beep()
            Misc.Pause(5000)
            continue
        Misc.SendMessage('taskState ' + str(taskState),255)
        doBandageHealing()
        if not checkNeedRunAwayDF():
            checkNeedRunAway()
        magicHealing()
        checkWeaponsDurability()
        #checkHaveNewArtifact()
        checkMagicSlayerBook()
        if taskState == 0:
            # taskState = 1
            curB = curboss()
            Misc.SendMessage('curboss ' + str(curB), 33)
            if curB == 0:
                taskState = 1
            elif curB == 1:
                taskState = 4
            elif curB == 2:
                taskState = 7
            elif curB == 3:
                taskState = 10
            elif curB == 4:
                taskState = 13
            elif curB == 5:
                taskState = 16
        #黑 爹 区 域 战 斗
        if taskState == 1:
            #BonesCut()
            isReach = gotoTargetByPoints(BossAreaPoint)
            if isReach or pathStep > 0:
                if isBossDead():
                    setState(3)
                elif findboss():
                    setState(2)
        if taskState == 2:
            #BonesCut()
            if isDemise:
                attackDF()
            else:
                attackEnemy()
                # Misc.SendMessage('isReach ' + str (isReach),255)
            if isBossDead():
                setState(3)
        #boss死 后
        if taskState == 3:
            #if Timer.Check('FeedWait') is False:
                #Misc.SendMessage('feedPet ', 33)
                #feedPet()
                #Timer.Create('FeedWait', feedTime)
            if not isHuman():
                changeWraithForm()
            setState(4)
        #1号房
        if taskState == 4:
            #BWPysl = BagItemsCounts(BWPysl0)
            # checkHaveNewArtifact()
            isReach = gotoTargetByPoints(toRoom1Point)
            if pathStep > 0 and checkRoomState() == 3:
                setState(7)
            elif isReach or (Player.Position.X > 473 and Player.Position.Y > 427 and Player.Position.Y < 438):
                setState(5)
        if taskState == 5:
            # Misc.SendMessage('taskState == 5',255)
            isReach = gotoWithCheckEnemy(room1Point)
            # Misc.SendMessage('isReach ' + str (isReach),255)
            if isReach and isBossDead():
                setState(6)
        if taskState == 6:
            isReach = gotoWithCheckEnemy(room1OutPoint)
            if isReach and findboss() is None:
                setState(7)
        #2号房
        if taskState == 7:
            #BWPysl0 = BagItemsCounts(BWPysl)
            # checkHaveNewArtifact()
            isReach = gotoTargetByPoints(toRoom2Point)
            if pathStep > 0 and checkRoomState() == 3:
                setState(10)
            elif isReach or (Player.Position.X > 461 and Player.Position.X < 475 and Player.Position.Y > 496):
                setState(8)
        if taskState == 8:
            isReach = gotoWithCheckEnemy(room2Point)
            if isReach and isBossDead():
                setState(9)
        if taskState == 9:
            isReach = gotoWithCheckEnemy(room2OutPoint)
            if isReach and findboss() is None:
                setState(10)
        #3号房
        if taskState == 10:
            #BWPysl = BagItemsCounts(BWPysl0)
            # checkHaveNewArtifact()
            isReach = gotoTargetByPoints(toRoom3Point)
            if pathStep > 0 and checkRoomState() == 3:
                setState(13)
            elif isReach or (Player.Position.X > 397 and Player.Position.X < 416 and Player.Position.Y > 504):
                setState(11)
        if taskState == 11:
            isReach = gotoWithCheckEnemy(room3Point)
            if isReach and isBossDead():
                setState(12)
        if taskState == 12:
            isReach = gotoWithCheckEnemy(room3OutPoint)
            if isReach and findboss() is None:
                setState(13)
                global findBossStep
                findBossStep = 0
        #4号房
        if taskState == 13:
            #BWPysl0 = BagItemsCounts(BWPysl)
            # checkHaveNewArtifact()
            isReach = gotoTargetByPoints(toRoom4Point)
            if pathStep > 0 and checkRoomState() == 3:
                setState(16)
            elif isReach or (Player.Position.X > 350 and Player.Position.X < 365 and Player.Position.Y > 478):
                setState(14)
        if taskState == 14:
            global boss4State
            Misc.SendMessage('boss4State  ' + str(boss4State), 255)
            isReach = room4GoRound(room4Point)
            # b = getNearestEnemy()
            if isBossDead():
                for i in range(2):
                    Player.ChatSay(0,"all come")
                    Misc.Pause(200)
                setState(15)
        if taskState == 15:
            isReach = gotoWithCheckEnemy(room4OutPoint)
            if isReach and findboss() is None:
                setState(16)
        #5号房
        if taskState == 16:
            #BWPysl = BagItemsCounts(BWPysl0)
            # checkHaveNewArtifact()
            isReach = gotoTargetByPoints(toRoom5Point)
            if pathStep > 0 and checkRoomState() == 3:
                setState(1)
            elif isReach or (Player.Position.X < 360 and Player.Position.Y > 423 and Player.Position.Y < 436):
                setState(17)
        if taskState == 17:
            isReach = gotoWithCheckEnemy(room5Point)
            if isReach and isBossDead():
                setState(18)
        if taskState == 18:
            isReach = gotoWithCheckEnemy(room5OutPoint)
            if isReach and findboss() is None:
                Misc.ScriptRun('包内物品进行保险.py')
                setState(1)
        
        if taskState == 20:
            isReach = gotoWithCheckEnemy(roomTestPoint, False, False, True)
            # if isReach and getNearestEnemy() is None:
            #     setState(1)

#启动魔法加血线程
# if useMagicHeal > 0:
#     thread.start_new_thread(doMagicHealing,())
#启动绷带线程
# if useBandage > 0:
#     thread.start_new_thread(doBandageHealing,())

#开启了绷带加血 就关掉RAE自带的绷带加血
if useBandage > 0:
    if BandageHeal.Status():
        BandageHeal.Stop()
#Misc.ScriptRun('包内物品进行保险.py')          
setBlades()
setWeapons()
checkSelfPets() 
Misc.Pause(1000)
setMagicSlayerBook()
main()

#427, 369 430, 369 430, 372 427, 372
#点是否在矩形内
# def isInside(x, y):
#     return (x >= 427 and x <= 430 and y >= 369 and y <= 372)


# p = Mobiles.FindBySerial(0x00012C59)
# isinstance(p, Mobiles)
# Misc.SendMessage(str(isDfAroundPlayer(p)), 255)
# while True:
#     Misc.SendMessage('is inside ' + str(isInside(Player.Position.X, Player.Position.Y)), 255)
    # doBandageHealing()
    # Misc.SendMessage('222222222222', 255)
    # doMagicHealing()
    # Misc.SendMessage('3333333333333', 255)
    # doCheckAttackBuff()
    # Misc.SendMessage('44444444444', 255)
    # Misc.Beep()
    # Misc.Pause(200)


        
